package com.gitee.wsl.compose.modifier.input

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Indication
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.waitForUpOrCancellation
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.Role
import com.gitee.wsl.ext.base.currentTimeMillis
import com.gitee.wsl.unit.angle.AngleUnit
import com.gitee.wsl.unit.angle.ext.clampAngle360
import com.gitee.wsl.unit.angle.ext.minus
import com.gitee.wsl.unit.angle.ext.normalize360
import com.gitee.wsl.unit.angle.toRadians
import kotlin.math.atan2


fun Modifier.throttleClick(
    timeout: Int = 1000,
    onClick: () -> Unit
) = composed {
    val interactionSource = remember { MutableInteractionSource() }
    val indication = LocalIndication.current
    Modifier.throttleClick(
        interactionSource = interactionSource,
        indication = indication,
        timeout = timeout,
        onClick = onClick
    )
}

// from emo
// 防抖点击
fun Modifier.throttleClick(
    interactionSource: MutableInteractionSource,
    indication: Indication?,
    timeout: Int = 250,
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onClick: () -> Unit
) = composed(
    inspectorInfo = debugInspectorInfo {
        name = "throttleClick"
        properties["timeout"] = timeout
        properties["enabled"] = enabled
        properties["onClickLabel"] = onClickLabel
        properties["role"] = role
        properties["onClick"] = onClick
        properties["indication"] = indication
        properties["interactionSource"] = interactionSource
    }
) {
    val throttleHandler = rememberSaveable(timeout, saver = ThrottleHandler.Saver) { ThrottleHandler(timeout) }
    Modifier.clickable(
        interactionSource = interactionSource,
        indication = indication,
        enabled = enabled,
        onClickLabel = onClickLabel,
        role = role,
        onClick = { throttleHandler.process(onClick) }
    )
}

internal class ThrottleHandler(private val timeout: Int = 500) {

    private var last: Long = 0

    fun process(event: () -> Unit) {
        val now = currentTimeMillis
        if (now - last > timeout) {
            event.invoke()
        }
        last = now
    }

    companion object {
        val Saver = Saver<ThrottleHandler, Long>(
            save = { it.last },
            restore = { ThrottleHandler().apply { last = it } }
        )
    }
}

private enum class ItemState { Pressed, Idle }

/**
 * Shrinks the card when clicked
 */
fun Modifier.bounceClick(
    targetValue: Float = 0.90f
) = composed {
    var itemState by remember { mutableStateOf(ItemState.Idle) }
    val scale by animateFloatAsState(if (itemState == ItemState.Pressed) targetValue else 1f)

    this
        .graphicsLayer {
            scaleX = scale
            scaleY = scale
        }
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = null,
            onClick = { }
        )
        .pointerInput(itemState) {
            awaitPointerEventScope {
                itemState = if (itemState == ItemState.Pressed) {
                    waitForUpOrCancellation()
                    ItemState.Idle
                } else {
                    awaitFirstDown(false)
                    ItemState.Pressed
                }
            }
        }
}

/**
 * No ripple clickable
 */
inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit) = composed {
    val interactionSource by remember { mutableStateOf(MutableInteractionSource()) }
    clickable(
        indication = null,
        interactionSource = interactionSource
    ) {
        onClick()
    }
}

@Composable
fun Modifier.clickableNoIndication(focusManager: FocusManager) =
    this.clickable(
        onClick = {
            focusManager.clearFocus()
        },
        // 去除点击效果
        indication = null,
        interactionSource = remember {
            MutableInteractionSource()
        }
    )

private fun computeAngleFromPointerInput(
    width: Float,
    height: Float,
    pointerX: Float,
    pointerY: Float,
    referenceAngle: AngleUnit,
): AngleUnit {
    val x = pointerX - (width / 2)
    val y = pointerY - (height / 2)
    val angleRadians = (atan2(y.toDouble(), x.toDouble()) - referenceAngle.radian).toRadians()

//    var angleDegrees = angleRadians.toDegrees()
//    while (angleDegrees < 0) angleDegrees += 360

    return angleRadians.normalize360()
}